package top.overstep.zboot.system.commons.shiro;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.springframework.data.redis.core.RedisTemplate;

import java.io.Serializable;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

@Slf4j
public class RedisSessionDao extends AbstractSessionDAO {

    private static final String SESSION_PREFIX = "session:prefix";

    private static final Gson gson;

    static {
        gson = new GsonBuilder().create();
    }

    /**
     * session 过期时间
     */
    @Setter
    private int expire = -1;

    @Setter
    private RedisTemplate<String, Session> redisTemplate;

    @Override
    protected Serializable doCreate(Session session) {
        if (session == null) {
            log.error("session is null");
            throw new UnknownSessionException("session is null");
        }
        Serializable sessionId = this.generateSessionId(session);
        this.assignSessionId(session, sessionId);
        this.saveSession(session);
        return sessionId;
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {
        if (sessionId == null) {
            log.warn("session id is empty");
            return null;
        }

        Session session = redisTemplate.opsForValue().get(sessionId);
        return session;
    }

    @Override
    public void update(Session session) throws UnknownSessionException {
        saveSession(session);
    }

    @Override
    public void delete(Session session) {
        if (session == null || session.getId() == null) {
            log.error("session or session id is null");
            throw new UnknownSessionException("session or session id is null");
        }
        redisTemplate.delete(getKey(session.getId()));
    }

    @Override
    public Collection<Session> getActiveSessions() {
        return null;
    }

    /**
     * 保存session
     *
     * @param session
     */
    private void saveSession(Session session) {
        if (session == null || session.getId() == null) {
            log.error("session or session id is null");
            throw new UnknownSessionException("session or session id is null");
        }
        String key = getKey(session.getId());
        redisTemplate.opsForValue().set(key, session, expire, TimeUnit.SECONDS);
    }

    /**
     * 获取key
     */
    private String getKey(Serializable sessionId) {
        return SESSION_PREFIX + ":" + gson.toJson(sessionId);
    }
}
